package com.ctshk.rpc.finance.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.SysApprovalType;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.model.TokenUser;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.rpc.finance.dto.advance.AdvanceChargeAmountDTO;
import com.ctshk.rpc.finance.dto.advance.AdvanceChargeApplyDTO;
import com.ctshk.rpc.finance.dto.advance.AdvanceChargeApplyDetailDTO;
import com.ctshk.rpc.finance.dto.advance.AdvanceChargeListDTO;
import com.ctshk.rpc.finance.dto.paidin.ChargeUsedRecordDTO;
import com.ctshk.rpc.finance.dto.paidin.CurrencyAmountCountDTO;
import com.ctshk.rpc.finance.entity.FinanceAdvanceCharge;
import com.ctshk.rpc.finance.entity.FinanceAdvanceChargeApply;
import com.ctshk.rpc.finance.entity.FinanceAdvanceChargeCurrencyAmount;
import com.ctshk.rpc.finance.json.FileJson;
import com.ctshk.rpc.finance.mapper.FinanceAdvanceChargeApplyMapper;
import com.ctshk.rpc.finance.mapper.FinanceAdvanceChargeCurrencyAmountMapper;
import com.ctshk.rpc.finance.mapper.FinanceAdvanceChargeMapper;
import com.ctshk.rpc.finance.mapper.FinancePaidInMapper;
import com.ctshk.rpc.finance.req.advance.*;
import com.ctshk.rpc.finance.service.IFinanceAdvanceChargeService;
import com.ctshk.rpc.system.dto.SysSupplierDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.service.ISysSupplierService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.ctshk.rpc.workflow.dto.ApprovalCheckDTO;
import com.ctshk.rpc.workflow.dto.ApprovalStartDTO;
import com.ctshk.rpc.workflow.service.ISysApprovalService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 财务预付 服务实现类
 * </p>
 *
 * @author 叶冠峰
 * @since 2021-04-08
 */
@DubboService
public class FinanceAdvanceChargeServiceImpl extends ServiceImpl<FinanceAdvanceChargeMapper, FinanceAdvanceCharge> implements IFinanceAdvanceChargeService {

    @Autowired
    private FinanceAdvanceChargeMapper advanceChargeMapper;
    @Autowired
    private FinanceAdvanceChargeCurrencyAmountMapper advanceChargeCurrencyAmountMapper;
    @Autowired
    private FinanceAdvanceChargeApplyMapper advanceChargeApplyMapper;
    @Autowired
    private FinancePaidInMapper paidInMapper;
    /*@Autowired
    private RedisTemplate<String, Object> redisTemplate;*/

    @DubboReference
    private ISysApprovalService sysApprovalService;
    @DubboReference
    private ISysUserService sysUserService;
    @DubboReference
    private ISysSupplierService sysSupplierService;



    /**
     * 查询供应商
     *
     * @param req
     * @param currentUser
     * @return
     */
    @Override
    public Result<AdvanceChargeListDTO> query(AdvanceChargeListReq req, TokenUser currentUser) {
        //查询供应商
        QueryWrapper<FinanceAdvanceCharge> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("supplier_id",req.getSupplierId());
    //    queryWrapper.like(StringUtils.isNotBlank(req.getSupplierName()),"supplier_name",req.getSupplierName());
    //    queryWrapper.like(StringUtils.isNotBlank(req.getSupplierContacts()),"supplier_contacts",req.getSupplierContacts());
        queryWrapper.eq("is_deleted",0);
        FinanceAdvanceCharge charge = advanceChargeMapper.selectOne(queryWrapper);
        if (charge == null){
            AdvanceChargeListDTO dto = new AdvanceChargeListDTO();
            Result<SysSupplierDTO> supplierDTOResult = sysSupplierService.query(req.getSupplierId());
            if (supplierDTOResult != null && supplierDTOResult.isSuccess()){
                SysSupplierDTO supplierDTO = supplierDTOResult.getData();
                charge = new FinanceAdvanceCharge();
                charge.setId(SnowflakeIdWorker.nextId());
                charge.setSupplierName(supplierDTO.getCnName());
                charge.setSupplierId(supplierDTO.getId());
                charge.setSupplierAddress(supplierDTO.getLocation());
                charge.setSupplierBankCard(supplierDTO.getBankCard());
                charge.setSupplierBankName(supplierDTO.getBankName());
                charge.setSupplierContacts(supplierDTO.getFinanceContactName());
                charge.setSupplierEmail(supplierDTO.getFinanceContactEmail());
                charge.setSupplierTelephone(supplierDTO.getFinanceContactMobile());
                charge.setCreateId(req.getUserId());
                charge.setGmtCreate(LocalDateTime.now());
                int insert = advanceChargeMapper.insert(charge);
                if (insert <= 0){
                    throw new BusinessException(SystemError.SYS_437);
                }
                dto = EntityUtil.copy(charge,AdvanceChargeListDTO.class);
            }
            return Result.success(dto);
        }
        //返回数据
        AdvanceChargeListDTO dto = EntityUtil.copy(charge,AdvanceChargeListDTO.class);
        //查询汇总信息
        List<AdvanceChargeAmountDTO> amountDTO = advanceChargeCurrencyAmountMapper.queryByCharge(charge.getId());
        dto.setAmountDTO(amountDTO);
        //申请记录
        List<AdvanceChargeApplyDTO> applyDTO = advanceChargeApplyMapper.queryByCharge(charge.getId());
        if (applyDTO != null && applyDTO.size() > 0){
            applyDTO.forEach(applyDto -> {
                //查询申请人
            //    UserDTO userDto = (UserDTO) redisTemplate.opsForValue().get(RedisConstants.ACCOUNT_QUERY_KEY + applyDto.getCreateId());
                UserDTO userDto = sysUserService.queryCacheUser(applyDto.getCreateId());
                if (userDto != null){
                    applyDto.setApplyUserName(userDto.getFullName());
                    applyDto.setApplyUserDept(userDto.getDept());
                }
            });
            dto.setApplyDTO(applyDTO);
        }
        //使用记录
        List<ChargeUsedRecordDTO> usedRecord = paidInMapper.queryListBySupplier(charge.getSupplierId());
        dto.setUsedRecord(usedRecord);
        return Result.success(dto);
    }

    /**
     * 申请
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result add(AdvanceChargeAddApplyReq req) {
        //查询供应商
        FinanceAdvanceCharge charge = getById(req.getAdvanceChargeId());
        if (charge == null || Objects.equals(charge.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_CHARGE_17026);
        }
        //附件
        List<FileJson> fileJson = req.getFileJson();
        if (fileJson.size() == 0){
            throw new BusinessException(SystemError.SYS_428,"fileJson");
        }
        //新增申请记录
        FinanceAdvanceChargeApply apply = EntityUtil.copy(req,FinanceAdvanceChargeApply.class);
        apply.setId(SnowflakeIdWorker.nextId());
        apply.setFileJson(JSON.toJSONString(fileJson));
        apply.setApprovalStatus(2);
        apply.setCreateId(req.getUserId());
        apply.setIsDeleted(0);
        int insert = advanceChargeApplyMapper.insert(apply);
        if (insert <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        //发起审批
        Long approvalId = startApproval(apply.getId(), apply.getId(), req.getUserId());
        apply.setApprovalId(approvalId);
        int update = advanceChargeApplyMapper.updateById(apply);
        if (update <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        return Result.success(apply.getId());
    }

    /**
     * 审批
     *
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result approval(AdvanceChargeApprovalApplyReq req) {
        //查询申请记录
        QueryWrapper<FinanceAdvanceChargeApply> queryWrapper1 = new QueryWrapper<>();;
        queryWrapper1.eq("approval_id",req.getApprovalId());
        queryWrapper1.eq("is_deleted",0);
        FinanceAdvanceChargeApply apply = advanceChargeApplyMapper.selectOne(queryWrapper1);
        if (apply == null){
            throw new BusinessException(SystemError.FINANCE_CHARGE_17026);
        }
        if (!Objects.equals(apply.getApprovalStatus(),2)){
            throw new BusinessException(SystemError.FINANCE_BILL_17012);
        }
        //更新状态
        apply.setApprovalStatus(req.getType());
        apply.setModifiedId(req.getUserId());
        int update = advanceChargeApplyMapper.updateById(apply);
        if (update <= 0){
            throw new BusinessException(SystemError.SYS_437);
        }
        Result<ApprovalCheckDTO> check = sysApprovalService.check(req.getApprovalId(), req.getUserId(), req.getType(), req.getComments());
        if (check == null || !check.getData().getIsFinish()){
            throw new BusinessException(SystemError.SYS_437);
        }
        //审批通过
        if (Objects.equals(req.getType(),3)){
            //查询统计
            QueryWrapper<FinanceAdvanceChargeCurrencyAmount> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("advance_charge_id",apply.getAdvanceChargeId());
            queryWrapper.eq("currency_id",apply.getCurrencyId());
            queryWrapper.eq("is_deleted",0);
            FinanceAdvanceChargeCurrencyAmount amount = advanceChargeCurrencyAmountMapper.selectOne(queryWrapper);
            if (amount != null){
                amount.setMoneyAmount(amount.getMoneyAmount().add(apply.getMoneyAmount()));
                amount.setAvailableAmount(amount.getAvailableAmount().add(apply.getMoneyAmount()));
                amount.setRemainingAmount(amount.getRemainingAmount().add(apply.getMoneyAmount()));
                amount.setModifiedId(req.getUserId());
                int update1 = advanceChargeCurrencyAmountMapper.updateById(amount);
                if (update1 <= 0){
                    throw new BusinessException(SystemError.SYS_437);
                }
            }else{
                amount = new FinanceAdvanceChargeCurrencyAmount();
                amount.setId(SnowflakeIdWorker.nextId());
                amount.setAdvanceChargeId(apply.getAdvanceChargeId());
                amount.setSupplierId(apply.getSupplierId());
                amount.setCurrencyId(apply.getCurrencyId());
                amount.setCurrency(apply.getCurrency());
                amount.setExchangeRate(apply.getExchangeRate());
                amount.setMoneyAmount(apply.getMoneyAmount());
                amount.setAvailableAmount(apply.getMoneyAmount());
                amount.setRemainingAmount(apply.getMoneyAmount());
                amount.setAmountUsed(BigDecimal.ZERO);
                amount.setGmtCreate(LocalDateTime.now());
                amount.setCreateId(req.getUserId());
                amount.setIsDeleted(0);
                int insert = advanceChargeCurrencyAmountMapper.insert(amount);
                if (insert <= 0){
                    throw new BusinessException(SystemError.SYS_437);
                }
            }
        }
        return Result.success(apply.getId());
    }

    /**
     * 申请详情
     *
     * @param req
     * @return
     */
    @Override
    public Result<AdvanceChargeApplyDetailDTO> applyDetail(AdvanceChargeApplyIdReq req) {
        //查询申请详情
        QueryWrapper<FinanceAdvanceChargeApply> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("is_deleted",0);
        queryWrapper.eq("id",req.getApplyId());
        queryWrapper.or();
        queryWrapper.eq("approval_id",req.getApplyId());
        FinanceAdvanceChargeApply apply = advanceChargeApplyMapper.selectOne(queryWrapper);
        if (apply == null){
            throw new BusinessException(SystemError.FINANCE_CHARGE_17026);
        }
        //查询供应商
        FinanceAdvanceCharge charge = getById(apply.getAdvanceChargeId());
        if (charge == null || Objects.equals(charge.getIsDeleted(),1)){
            throw new BusinessException(SystemError.FINANCE_CHARGE_17025);
        }
        //返回数据
        AdvanceChargeApplyDetailDTO dto = EntityUtil.copy(apply,AdvanceChargeApplyDetailDTO.class);
        dto.setSupplierName(charge.getSupplierName());
        dto.setSupplierTelephone(charge.getSupplierTelephone());
        dto.setSupplierContacts(charge.getSupplierContacts());
        dto.setSupplierBankName(charge.getSupplierBankName());
        dto.setSupplierBankCard(charge.getSupplierBankCard());
        dto.setSupplierAddress(charge.getSupplierAddress());
        dto.setSupplierEmail(charge.getSupplierEmail());
        //附件
        if (StringUtils.isNotBlank(apply.getFileJson())){
            dto.setFileJson(JSON.parseArray(apply.getFileJson(),FileJson.class));
        }
        //查询申请人
        UserDTO userDto = sysUserService.queryCacheUser(apply.getCreateId());
        if (userDto != null){
            dto.setApplyUserName(userDto.getFullName());
            dto.setApplyUserDept(userDto.getDept());
        }
        return Result.success(dto);
    }

    /**
     * 申请付款-查询供应商预付款额度
     *
     * @param req
     * @return
     */
    @Override
    public Result<List<CurrencyAmountCountDTO>> queryQuota(AdvanceChargeQueryQuotaReq req) {
        List<CurrencyAmountCountDTO> list = advanceChargeCurrencyAmountMapper.sumCurrencyAmountBySupplier(req.getSupplierId());
        if(CollectionUtils.isEmpty(list)){
            return Result.success(null);
        }
        return Result.success(list);
    }


    /**
     * 发起审批流程
     * @param id
     * @param businessId
     * @param userId
     */
    private Long startApproval(Long id, Long businessId, Long userId) {
        Map<String, Object> extendParams = new HashMap<>();
        extendParams.put("id", id);
        try{
            Result<ApprovalStartDTO> approvalResult = sysApprovalService.start(SystemBusinessType.FINANCE.getCode(),
                    SysApprovalType.PREPAID_FINANCE.getCode(), businessId,
                    userId, null, JSON.toJSONString(extendParams));
            if (!approvalResult.isSuccess()) {
                throw new BusinessException(SystemError.CUSTOM_ORDER_4044);
            }
            return approvalResult.getData().getApprovalId();
        }catch (Exception e){
            throw new BusinessException(SystemError.SYS_422);
        }
    }

    /**
     * 业务审批
     * @param approvalId    审批id(必填)
     * @param userId        审批人id(必填)
     * @param status        状态-ApprovalStatus枚举code 0 撤回 3 审批不通过 4 审批通过(必填)
     * @param comments      通过或拒绝评论说明(非必填)
     * @return
     */
    private Boolean checkApproval(Long approvalId, Integer status, Long userId,String comments){
        Result<ApprovalCheckDTO> result = sysApprovalService.check(approvalId, userId, status, comments);
        if (result != null && result.isSuccess()){
            return result.getData().getIsFinish();
        }
        return false;
    }

}
